package com.jtpay.unionpay.product.service;

import android.accessibilityservice.AccessibilityService;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Toast;
import com.jtpay.unionpay.product.MainActivity;
import com.jtpay.unionpay.product.R;
import com.jtpay.unionpay.product.dbUtils.UnionPayProductDbUtil;
import com.jtpay.unionpay.product.http.ApiHelper;
import com.jtpay.unionpay.product.http.listener.TransApiResultListener;
import com.jtpay.unionpay.product.model.ProductBean;
import com.jtpay.unionpay.product.utils.ActivityHelper;
import com.jtpay.unionpay.product.utils.LogUtil;
import com.jtpay.unionpay.product.utils.PayFileUtil;
import com.jtpay.unionpay.product.utils.SharedPreferenceUtil;
import com.uuzuche.lib_zxing.activity.CodeUtils;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import static com.jtpay.unionpay.product.utils.ActivityHelper.*;
import static com.jtpay.unionpay.product.utils.PayContext.*;
import static com.jtpay.unionpay.product.utils.PayFileUtil.IMG_DIR_PATH;

/**
 * Description:
 * Date : 2018/06/01 09:06
 * Author : Joe
 */

public class UnionPayProductService extends AccessibilityService {
    private boolean step1 = false;//union pay s1 start
    private boolean step2 = false;//union pay s2 click set
    private boolean step3 = false;//union pay s3 set money
    private boolean step4 = false;//union pay s4 set remark
    private boolean step5 = false;//union pay s5 click set commit
    private boolean step6 = false;//union pay s6 screen shot
    private boolean step7 = false;//union pay s7 click clean set
    private boolean isUnionPayOrderIdOn = false;//get union pay order id
    private int submitX = -1;
    private int submitY = -1;

    private ProductBean payQrModel;
    private UnionPayProductDbUtil payProductDbUtil;
    private SharedPreferenceUtil sharedPreferenceUtil = new SharedPreferenceUtil();

    {
        payProductDbUtil = new UnionPayProductDbUtil();
    }

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        CharSequence charSequence = event.getPackageName();
        if (charSequence == null) {
            return;
        }
        String nowPackageName = charSequence.toString();
        if (nowPackageName.equals(UNION_PAY_PACKAGE_NAME)) {
            AccessibilityNodeInfo rootNode = this.getRootInActiveWindow();
            String className = event.getClassName().toString();
            switch (className) {
                case UNION_PAY_MAIN_ACTIVITY:
                    LogUtil.log("UNION_PAY_MAIN_ACTIVITY");
                    doGetUPAccountUI(rootNode);
                    doCallQrCodeUI(rootNode);
                    break;
                case UNION_PAY_REACT_NATIVE_ACTIVITY:
                    LogUtil.log("UNION_PAY_REACT_NATIVE_ACTIVITY");
                    if (isUnionPayOrderIdOn) {
                        break;
                    }
                    payQrModel = getProductBean();
                    if (payQrModel == null) {
                        LogUtil.log("product bean null");
                        ActivityHelper.startProductMainActivity();
                        break;
                    }
                    if (!step1) {
                        step1 = true;
                        LogUtil.log("step1");
                        startQrSetUICycle();
                        dealBlankPage();
                    }
                    clickQrSetUILabel(rootNode);
                    break;
            }
            switch (event.getEventType()) {
                case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
                case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
                    LogUtil.log("AccessibilityEvent " + className);
                    clickQrSetUILabel(rootNode);
                    clickQrSetCommitUI();
                    break;
            }
        }
    }

    /**
     * do get union pay account info
     *
     * @param rootNode AccessibilityNodeInfo
     */
    private void doGetUPAccountUI(AccessibilityNodeInfo rootNode) {
        if (rootNode == null || GetAccountStatus != 1) {
            return;
        }
        if (rootNode.getChildCount() == 0) {
            if (rootNode.getText() != null && rootNode.getText().toString()
                    .equals(getString(R.string.mine))) {
                reSetStep();
                getUPAccount(rootNode);
            }
        } else {
            for (int i = 0; i < rootNode.getChildCount(); i++) {
                if (rootNode.getChild(i) != null) {
                    doGetUPAccountUI(rootNode.getChild(i));
                }
            }
        }
    }

    /**
     * get account ui
     *
     * @param nodeInfo AccessibilityNodeInfo
     */
    private void getUPAccount(AccessibilityNodeInfo nodeInfo) {
        if (nodeInfo == null) {
            return;
        }
        List<AccessibilityNodeInfo> list = null;
        try {
            list = getRootInActiveWindow()
                    .findAccessibilityNodeInfosByViewId(UNION_PAY_PACKAGE_NAME + ":id/tv_name");
        } catch (Exception e) {
            e.printStackTrace();
            LogUtil.log("findAccessibility NodeInfo ByViewId error : " + e.getMessage());
        }
        // 点击返回上一界面
        if (list != null && list.size() >= 1) {
            GetAccountStatus = 2;
            MainActivity.getInstance().getUPAccountResult(list.get(0).getText().toString());
            GetAccountStatus = 0;
        }
    }

    /**
     * open qr show ui
     *
     * @param info AccessibilityNodeInfo
     */
    private void doCallQrCodeUI(AccessibilityNodeInfo info) {
        if (info == null || GetAccountStatus != 0) {
            return;
        }
        if (info.getChildCount() == 0) {
            if (info.getText() != null && info.getText().toString()
                    .equals(getString(R.string.card_package))) {
                reSetStep();
                clickButton(info);
                doClickInfoWithContent(getRootInActiveWindow(), getString(R.string.receivables));
            } else if (info.getText() != null && info.getText().toString()
                    .equals(getString(R.string.receivables))) {
                reSetStep();
                clickButton(info);
            }
        } else {
            for (int i = 0; i < info.getChildCount(); i++) {
                if (info.getChild(i) != null) {
                    doCallQrCodeUI(info.getChild(i));
                }
            }
        }
    }

    /**
     * @param nodeInfo AccessibilityNodeInfo
     */
    private void clickQrSetUILabel(AccessibilityNodeInfo nodeInfo) {
        if (nodeInfo == null) {
            return;
        }
        if (payQrModel == null) {
            LogUtil.log("clickQrSetUILabel product bean null");
            return;
        }
        if (nodeInfo.getChildCount() == 0 && nodeInfo.getText() != null) {
//            LogUtil.log("nodeInfo : " + nodeInfo.getText().toString());
            if (nodeInfo.getText().toString().equals(getString(R.string.set_money))
                    && step1 && !step2) {
                step2 = true;
//                MainActivity.getInstance().log(payQrModel.toString());
                LogUtil.log("step2");
                clickButtonWithRoot(nodeInfo);
            } else if (nodeInfo.getText().toString().equals(getString(R.string.money_tips_content))
                    && step2 && !step3) {
                step3 = true;
                LogUtil.log("step3");
                setContent(nodeInfo, payQrModel.getMoney());
            } else if (nodeInfo.getText().toString().equals(getString(R.string.remarks_tips_content))
                    && step3 && !step4) {
                step4 = true;
                LogUtil.log("step4");
                setContent(nodeInfo, payQrModel.getRemarks());
            } else if (nodeInfo.getText().toString().endsWith(getString(R.string.submit))
                    && step4 && !step5) {
                step5 = true;
                LogUtil.log("step5");
                clickButtonWithRoot(nodeInfo);
            /*} else if (nodeInfo.getText().toString().endsWith("保存图片") && step5 && !step6) {
                step6 = true;
                LogUtil.log("step6");
                clickButtonWithRoot(nodeInfo);*/
            } else if (nodeInfo.getText().toString().endsWith(getString(R.string.clear_money))
                    && step5 && !step6) {
                screenShotDeal(getRootInActiveWindow());
            } else if (nodeInfo.getText().toString().equals(getString(R.string.clear_money))
                    && step6 && !step7) {
                step7 = true;
                LogUtil.log("step7");
                clickButtonWithRoot(nodeInfo);
                reSetStep();
            } else if (nodeInfo.getText().toString().endsWith(getString(R.string.submit))
                    && step1 && step2) {
                submitX = sharedPreferenceUtil.SP_READ_INT(this, SUBMIT_X_KEY);
                submitY = sharedPreferenceUtil.SP_READ_INT(this, SUBMIT_Y_KEY);
                if (submitX < 0 || submitY < 0) {
                    Rect outBounds = new Rect();
                    nodeInfo.getBoundsInScreen(outBounds);
                    submitX = (outBounds.left + outBounds.right) / 2;
                    submitY = (outBounds.top + outBounds.bottom) / 2;
                    sharedPreferenceUtil.SP_SAVE_INT(this, SUBMIT_X_KEY, submitX);
                    sharedPreferenceUtil.SP_SAVE_INT(this, SUBMIT_Y_KEY, submitY);
//                    inputClick(submitX, submitY);
                }
            }
        } else {
            for (int i = 0; i < nodeInfo.getChildCount(); i++) {
                if (nodeInfo.getChild(i) != null) {
                    clickQrSetUILabel(nodeInfo.getChild(i));
                }
            }
        }
    }

    /**
     * qr code set money remark info
     */
    private void clickQrSetCommitUI() {
        if (step2 && !step3) {
            if (submitX < 0) {
//                submitX = 540;
                submitX = sharedPreferenceUtil.SP_READ_INT(this, SUBMIT_X_KEY, 540);
            } else if (submitY < 0) {
//                submitY = 660;
                submitY = sharedPreferenceUtil.SP_READ_INT(this, SUBMIT_Y_KEY, 660);
            }
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (step2 && !step3 && submitX > 0 && submitY > 0) {
                        inputClick(submitX, submitY);
                        clickQrSetCommitUI();
                    }
                }
            }, 2000);
        }
    }

    /**
     * cycle start qr set info ui
     */
    private void startQrSetUICycle() {
        if (step1 && !step2) {
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (step1 && !step2 && payQrModel != null) {
                        clickQrSetUILabel(getRootInActiveWindow());
                        startQrSetUICycle();
                    }
                }
            }, 1000);
        }
    }

    /**
     * deal BlankPage
     */
    private void dealBlankPage() {
        if (step1 && !step2) {
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (step1 && !step2 && payQrModel != null) {
                        performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
                    }
                }
            }, 5000);
        }
    }

    private SimpleDateFormat simpleDateFormat =
            new SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault());

    /**
     * screen shot deal
     */
    private void screenShotDeal(final AccessibilityNodeInfo nodeInfo) {
        if (step5 && !step6) {
            String fileName = "imgScreenShot" + simpleDateFormat.format(new Date()) + ".png";
            PayFileUtil.saveScreenShot(fileName);
            CodeUtils.analyzeBitmap(IMG_DIR_PATH + File.separator + fileName,
                    new CodeUtils.AnalyzeCallback() {
                        @Override
                        public void onAnalyzeSuccess(Bitmap mBitmap, String result) {
                            getUnionPayOrderId(result);
                        }

                        @Override
                        public void onAnalyzeFailed() {
                            LogUtil.log("ZXing Analyze onAnalyzeFailed");
                            step6 = true;
                            clickQrSetUILabel(nodeInfo);
                        }
                    });
        }
    }

    /**
     * get UnionPay OrderId
     *
     * @param result String
     */
    private void getUnionPayOrderId(String result) {
        if (isUnionPayOrderIdOn) {
            LogUtil.log("getUnionPayOrderId already on");
            return;
        }
        LogUtil.log("step6");
        isUnionPayOrderIdOn = true;
        payQrModel.setCodeUrl(result);
        payProductDbUtil.update(payQrModel);
//      LogUtil.log("ZXing Analyze Result : " + result);
        MainActivity.getInstance().log(payQrModel.toString());
        ApiHelper.getInstance(UnionPayProductService.this)
                .getUPOrderIdAPI(new TransApiResultListener<String>() {
                    @Override
                    public void trans(String orderId) {
                        payQrModel.setUnionPayOrderId(orderId);
                        uploadQrInfo(payQrModel);
                    }
                });
    }

    /**
     * upload Qr Info
     *
     * @param payQrModel ProductBean
     */
    private void uploadQrInfo(ProductBean payQrModel) {
        ApiHelper.getInstance(UnionPayProductService.this)
                .uploadQrInfoAPI(payQrModel.getRemarks(), payQrModel.getCodeUrl()
                        , payQrModel.getUnionPayOrderId(), new TransApiResultListener<String>() {
                            @Override
                            public void trans(String msg) {
                                LogUtil.log("upload " + msg);
                                step6 = true;
                                clickQrSetUILabel(getRootInActiveWindow());
                                // MARK: 2018/07/31 wait for next task
                                MainActivity.getInstance().startProduct(null);
                            }
                        });
    }

    /**
     * @param info    AccessibilityNodeInfo
     * @param content search key value
     */
    private void doClickInfoWithContent(AccessibilityNodeInfo info, String content) {
        if (info == null) {
            return;
        }
        if (info.getChildCount() == 0) {
            if (info.getText() != null && info.getText().toString().equals(content)) {
                clickButton(info);
            }
        } else {
            for (int i = 0; i < info.getChildCount(); i++) {
                if (info.getChild(i) != null) {
                    doClickInfoWithContent(info.getChild(i), content);
                }
            }
        }
    }

    private void clickButton(AccessibilityNodeInfo info) {
        AccessibilityNodeInfo parent = info;
        while (parent != null) {
            if (parent.isClickable()) {
                parent.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                break;
            }
            parent = parent.getParent();
        }
    }

    /**
     * @param nodeInfo use root command click
     */
    private void clickButtonWithRoot(final AccessibilityNodeInfo nodeInfo) {
//        LogUtil.log("clickButtonWithRoot");
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                Rect outBounds = new Rect();
                nodeInfo.getBoundsInScreen(outBounds);
                inputClick((outBounds.left + outBounds.right) / 2,
                        (outBounds.top + outBounds.bottom) / 2);
            }
        }, 300);
    }

    /**
     * if (!getTopActivity().endsWith("UPReactNativeActivity")) {
     * return;
     * }
     *
     * @param info    AccessibilityNodeInfo
     * @param content message info
     */

    private void setContent(AccessibilityNodeInfo info, String content) {
        Bundle arguments = new Bundle();
        arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, content);
        info.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
    }

    @Override
    public void onInterrupt() {
        Toast.makeText(this, "onInterrupt", Toast.LENGTH_SHORT).show();
    }

    /**
     * reset control logic
     */
    private void reSetStep() {
        LogUtil.log("do reSetStep");
        step1 = false;
        step2 = false;
        step3 = false;
        step4 = false;
        step5 = false;
        step6 = false;
        step7 = false;
        isUnionPayOrderIdOn = false;
    }

    private ProductBean getProductBean() {
        if (payProductDbUtil != null) {
            return payProductDbUtil.getOneForProduct();
        }
        return null;
//        return new ProductBean(
//                "0.1", "123456", "0");

    }
}
